const { Sequelize, DataTypes } = require("sequelize");
const config = require("./config");
const moment = require("moment");

console.log("init sequelize...");

// function generateId() {
//   return uuid.v4();
// }

// 创建一个sequelize对象实例
var sequelize = new Sequelize(
  config.database,
  config.username,
  config.password,
  {
    host: config.host,
    dialect: config.dialect,
    pool: {
      max: 5,
      min: 0,
      idle: 30000,
    },
    tunezone: "+8:00", // 东八时区
  }
);

// const ID_TYPE = DataTypes.UUID;

function defineModel(name, attributes) {
  var attrs = {};
  for (let key in attributes) {
    let value = attributes[key];
    if (typeof value === "object" && value["type"]) {
      value.allowNull = value.allowNull || false;
      attrs[key] = value;
    } else {
      attrs[key] = {
        type: value,
        allowNull: false,
      };
    }
  }
  attrs.id = {
    type: DataTypes.UUID,
    defaultValue: Sequelize.UUIDV4,
    primaryKey: true,
  };
  attrs.createdTime = {
    type: DataTypes.STRING,
    allowNull: false,
    defaultValue: moment().format("YYYY-MM-DD HH:mm"),
  };
  attrs.updatedTime = {
    type: DataTypes.STRING,
    allowNull: false,
    defaultValue: moment().format("YYYY-MM-DD HH:mm"),
  };
  // attrs.version = {
  //   type: Sequelize.BIGINT,
  //   allowNull: false,
  // };

  // console.log(
  //   "model defined for table: " +
  //     name +
  //     "\n" +
  //     JSON.stringify(
  //       attrs,
  //       function (k, v) {
  //         if (k === "type") {
  //           for (let key in Sequelize) {
  //             if (key === "ABSTRACT" || key === "NUMBER") {
  //               continue;
  //             }
  //             let dbType = Sequelize[key];
  //             if (typeof dbType === "function") {
  //               if (v instanceof dbType) {
  //                 if (v._length) {
  //                   return `${dbType.key}(${v._length})`;
  //                 }
  //                 return dbType.key;
  //               }
  //               if (v === dbType) {
  //                 return dbType.key;
  //               }
  //             }
  //           }
  //         }
  //         return v;
  //       },
  //       "  "
  //     )
  // );

  return sequelize.define(
    name,
    attrs,
    {
      tableName: name,
      timestamps: false,
      hooks: {
        beforeValidate: function (obj) {
          if (obj.isNewRecord) {
            console.log("will create entity...");
            if (!obj.id) {
              obj.id = Sequelize.UUIDV4;
            }
            // obj.version = 0;
          } else {
            console.log("will update entity...");
            // obj.version++;
          }
        },
        beforeUpdate: function (obj) {
          const now = moment().format("YYYY-MM-DD HH:mm");
          obj.updatedTime = now;
        },
      },
    },
    {
      define: { freezeTableName: true },
    }
  );
}

const TYPES = [
  "STRING",
  "INTEGER",
  "BIGINT",
  "TEXT",
  "DOUBLE",
  "DATEONLY",
  "BOOLEAN",
];

var exp = {
  defineModel: defineModel,
  sync: async () => {
    // only allow create ddl in non-production environment:
    if (process.env.NODE_ENV !== "production") {
      // sequelize.sync({ force: true });
      try {
        await sequelize.sync({ force: true });
        console.log("sync done,db inited");
        process.exit(0);
      } catch (error) {
        console.log(`failed:${error}`);
        process.exit(0);
      }
    } else {
      throw new Error("Cannot sync() when NODE_ENV is set to 'production'.");
    }
  },
};

for (let type of TYPES) {
  exp[type] = Sequelize[type];
}

// exp.ID = ID_TYPE;
// exp.generateId = Sequelize.UUIDV4;

module.exports = exp;
